import sys
import re
import os
from pathlib import Path


def renaming(renaming_list):
    print("Renaming, wait ...")
    i=0
    for src, dst in renaming_list:
        try:
            os.rename(src, dst)
        except PermissionError:
            print(f'Error: Permission denied for: "{src}"')
        except OSError as e:
            print(f'While renaming: "{src}"\nan unexpected OS error occurred: {e}')
        else:
            i += 1
    print(f'{i} files renamed')


def validate_args(args):
    if args.directory is None:
        print('Directory argument was not provided, so renaming in directory where executable is')
        if getattr(sys, 'frozen', False):
            # frozen
            args.directory = os.path.dirname(sys.executable)
        else:
            # running as python
            try:
                app_full_path = os.path.realpath(__file__)
                args.directory = os.path.dirname(app_full_path)
            except NameError:
                args.directory = os.getcwd()
    elif not Path(args.directory).is_dir():
        sys.exit(f'Wrong directory argument, directory does not exist: "{args.directory}"')
    if args.extensions is None:
        sys.exit(f'Missing extensions argument. Example passing two extensions separated by a "*" character: --extensions mp4*mp3')
    extensions = args.extensions.split('*')
    extensions = [f'.{ext}' for ext in extensions if ext]
    args.extensions = extensions
    if not args.extensions:
        raise ValueError(f'Wrong filename extensions were provided. Example passing two extensions separated by a "*" character: --extensions mp4*mp3')
    if args.regextodelete is None and args.regextospace is None:
        sys.exit(f"No regex were provided, regextodelete or regextospace argument needed, example: --regextodelete [%#] --regextospace [^a-zA-Z0-9]")
    if not args.regextodelete and not args.regextospace:
        raise ValueError(f"Wrong regex were provided, proper regextodelete or regextospace argument needed, example: --regextodelete [%#] --regextospace [^a-zA-Z0-9]")
    print('rename filenames:')
    print('  confirm_renaming =', args.confirm_renaming)
    print('  directory        =', f'"{args.directory}"')
    print('  extensions       =', args.extensions)
    print('  regextodelete    =', args.regextodelete)
    print('  regextospace     =', args.regextospace)
    print('')
    return args


def rename(confirm_renaming:bool,  directory:str, extensions:list, regextodelete:str='', regextospace:str=''):
    files = (file for file in Path(directory).iterdir() if file.suffix in extensions)
    renaming_list = []
    executive_stem = Path(__file__).stem
    for file in files:
        if file.stem == executive_stem:
            continue
        original_stem = file.stem
        new_stem = file.stem

        if regextodelete:
            new_stem = re.sub(rf'{regextodelete}', '', original_stem) # example pattern could be raw string: r'[#%]'
             
        if regextospace:
            new_stem = re.sub(rf'{regextospace}', ' ', new_stem)  # example pattern could be raw string: r'[^a-zA-Z0-9]'
        
        if not new_stem == original_stem:
            print('new name:', f'"{new_stem}{file.suffix}"', '     original:', f'"{file.name}"')
            renaming_list.append([file.parent / f'{original_stem}{file.suffix}',
                                  file.parent / f'{new_stem}{file.suffix}'])
    print('')
    if not confirm_renaming:
        print('Argument --confirm_renaming was not provided, so renaming files')

    if not renaming_list:
        print('No files found to be renamed')

    if renaming_list:
        if confirm_renaming:
            user_response = input('Would you like to start renaming? [Y/N]: ').strip().lower()
            if user_response in ('y', 'yes'):  
                renaming(renaming_list)
            else:
                print("Aborting")
        else:
            renaming(renaming_list)
    print('Done')


if __name__ == "__main__":
    """
    usage:
    python "rename filenames.py" --confirm_renaming --extensions py*txt --regextodelete [%#] --regextospace [^^a-zA-Z0-9]
    or
    "rename filenames.exe" --extensions py*txt --regextodelete [%#] --regextospace [^a-zA-Z0-9]
    """

    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("--confirm_renaming", action="store_true", help="flag will cause script to stop and wait for user to confirm renaming")
    parser.add_argument("--directory",     type=str, help='directory were renming will be done, if not provided, it will be current directory')
    parser.add_argument("--extensions",    type=str, help='string with filename extensions separated by "*" character')
    parser.add_argument("--regextodelete", type=str, help="regex that deletes characters")
    parser.add_argument("--regextospace",  type=str, help="regex that replaces characters to a space character")
    args = parser.parse_args()
    args = validate_args(args)
    rename(args.confirm_renaming, args.directory, args.extensions, args.regextodelete, args.regextospace)
